home *** CD-ROM | disk | FTP | other *** search
/ ftp.mactech.com 2010 / ftp.mactech.com.tar / ftp.mactech.com / macintosh-c / macc-carbon-demos-nonbinhex.sit / macc-carbon-demos-nonbinhex / chap18-demo-classic events / Files.c < prev    next >
C/C++ Source or Header  |  2001-06-11  |  22KB  |  778 lines

  1. // *******************************************************************************************
  2. // Files.c
  3. // *******************************************************************************************
  4.  
  5. // ………………………………………………………………………………………………………………………………………………………………………………………………………………………… includes
  6.  
  7. #include "Files.h"
  8.  
  9. // …………………………………………………………………………………………………………………………………………………………………………………………………… global variables
  10.  
  11. Boolean            gRunningOnX = false;
  12. Boolean            gDone;
  13. SInt16            gAppResFileRefNum;
  14. NavEventUPP    gGetFilePutFileEventFunctionUPP ;
  15. Boolean            gQuittingApplication = false;
  16.  
  17. extern SInt16        gCurrentNumberOfWindows;
  18. extern Rect            gDestRect,gViewRect;
  19.  
  20. // ************************************************************************************** main
  21.  
  22. void  main(void)
  23. {
  24.     MenuBarHandle    menubarHdl;
  25.     SInt32                response;
  26.     MenuRef                menuRef;
  27.  
  28.     // ……………………………………………………………………………………………………………………………………………………………………………………………… do preliminaries
  29.  
  30.     doPreliminaries();
  31.  
  32.     // ………………………………………………………………………………………… save application's resource file file reference number
  33.  
  34.     gAppResFileRefNum = CurResFile();
  35.  
  36.     // ……………………………………………………………………………………………………………………………………………………………………… set up menu bar and menus
  37.     
  38.     menubarHdl = GetNewMBar(rMenubar);
  39.     if(menubarHdl == NULL)
  40.         doErrorAlert(MemError());
  41.     SetMenuBar(menubarHdl);
  42.     DrawMenuBar();
  43.  
  44.     Gestalt(gestaltMenuMgrAttr,&response);
  45.     if(response & gestaltMenuMgrAquaLayoutMask)
  46.     {
  47.         menuRef = GetMenuRef(mFile);
  48.         if(menuRef != NULL)
  49.         {
  50.             DeleteMenuItem(menuRef,iQuit);
  51.             DeleteMenuItem(menuRef,iQuit - 1);
  52.         }
  53.  
  54.         gRunningOnX = true;
  55.     }
  56.  
  57.     // ……………………………………………………………………………………………………………………………………… install required Apple event handlers
  58.  
  59.     doInstallAEHandlers();
  60.  
  61.     // …………… get universal procedure pointer to main Navigation Services services event function
  62.  
  63.     gGetFilePutFileEventFunctionUPP  = 
  64.                                                                 NewNavEventUPP((NavEventProcPtr) getFilePutFileEventFunction);
  65.  
  66.     // ……………………………………………………………………………………………………………………………………………………………………………………………… enter event loop
  67.  
  68.     eventLoop();
  69. }
  70.  
  71. // ********************************************************************************* eventLoop
  72.  
  73. void  eventLoop(void)
  74. {
  75.     EventRecord eventStructure;
  76.  
  77.     gDone = false;
  78.  
  79.     while(!gDone)
  80.     {
  81.         if(WaitNextEvent(everyEvent,&eventStructure,180,NULL))
  82.             doEvents(&eventStructure);
  83.         else
  84.             doSynchroniseFiles();
  85.  
  86.         if(gRunningOnX && gQuittingApplication)
  87.             doCloseCommand(kNavSaveChangesQuittingApplication);
  88.     }
  89. }
  90.  
  91. // *************************************************************************** doPreliminaries
  92.  
  93. void  doPreliminaries(void)
  94. {
  95.     MoreMasterPointers(448);
  96.     InitCursor();
  97.   FlushEvents(everyEvent,0);
  98. }
  99.  
  100. // *********************************************************************** doInstallAEHandlers
  101.  
  102. void  doInstallAEHandlers(void)
  103. {
  104.     OSErr    osError;
  105.  
  106.     osError = AEInstallEventHandler(kCoreEventClass,kAEOpenApplication,
  107.                                     NewAEEventHandlerUPP((AEEventHandlerProcPtr) openAppEventHandler),
  108.                                     0L,false);
  109.     if(osError != noErr)    doErrorAlert(eInstallHandler);
  110.  
  111.     osError = AEInstallEventHandler(kCoreEventClass,kAEReopenApplication,
  112.                                     NewAEEventHandlerUPP((AEEventHandlerProcPtr) reopenAppEventHandler),
  113.                                     0L,false);
  114.     if(osError != noErr)    doErrorAlert(eInstallHandler);
  115.  
  116.     osError = AEInstallEventHandler(kCoreEventClass,kAEOpenDocuments,
  117.                                     NewAEEventHandlerUPP((AEEventHandlerProcPtr) openAndPrintDocsEventHandler),
  118.                                     kOpen,false);
  119.     if(osError != noErr)    doErrorAlert(eInstallHandler);
  120.  
  121.     osError = AEInstallEventHandler(kCoreEventClass,kAEPrintDocuments,
  122.                                     NewAEEventHandlerUPP((AEEventHandlerProcPtr) openAndPrintDocsEventHandler),
  123.                                     kPrint,false);
  124.     if(osError != noErr)    doErrorAlert(eInstallHandler);
  125.  
  126.     osError = AEInstallEventHandler(kCoreEventClass,kAEQuitApplication,
  127.                                     NewAEEventHandlerUPP((AEEventHandlerProcPtr) quitAppEventHandler),
  128.                                     0L,false);
  129.     if(osError != noErr)    doErrorAlert(eInstallHandler);
  130. }
  131.  
  132. // ********************************************************************************** doEvents
  133.  
  134. void    doEvents(EventRecord *eventStrucPtr)
  135. {
  136.     switch(eventStrucPtr->what)
  137.     {
  138.         case kHighLevelEvent:
  139.             AEProcessAppleEvent(eventStrucPtr);
  140.             break;
  141.  
  142.         case mouseDown:
  143.             doMouseDown(eventStrucPtr);
  144.             break;
  145.  
  146.         case keyDown:
  147.             if((eventStrucPtr->modifiers & cmdKey) != 0)
  148.             {
  149.                 doAdjustMenus();
  150.                 doMenuChoice(MenuEvent(eventStrucPtr));
  151.             }
  152.             break;
  153.  
  154.         case updateEvt:
  155.             doUpdate(eventStrucPtr);
  156.             break;
  157.  
  158.         case osEvt:
  159.             switch((eventStrucPtr->message >> 24) & 0x000000FF)
  160.             {
  161.                 case suspendResumeMessage:
  162.                     if((eventStrucPtr->message & resumeFlag) == 1)
  163.                         SetThemeCursor(kThemeArrowCursor);
  164.                     break;
  165.             }
  166.             break;
  167.     }
  168. }
  169.  
  170. // ******************************************************************************* doMouseDown
  171.  
  172. void    doMouseDown(EventRecord *eventStrucPtr)
  173. {
  174.     WindowRef                windowRef;
  175.     WindowPartCode    partCode;
  176.     OSStatus                osStatus;                                                                                                                             /////
  177.     Boolean                    handled = false;                                                                                                              /////
  178.     SInt32                    itemSelected;                                                                                                                     /////
  179.  
  180.     partCode = FindWindow(eventStrucPtr->where,&windowRef);
  181.     
  182.     switch(partCode)
  183.     {
  184.         case inMenuBar:
  185.             doAdjustMenus();
  186.             doMenuChoice(MenuSelect(eventStrucPtr->where));
  187.             break;
  188.  
  189.         case inContent:
  190.             if(windowRef != FrontWindow())
  191.                 SelectWindow(windowRef);
  192.             break;
  193.  
  194.         case inGoAway:
  195.             if(TrackGoAway(windowRef,eventStrucPtr->where) == true)
  196.                 doCloseCommand(kNavSaveChangesClosingDocument);
  197.             break;
  198.  
  199.         case inProxyIcon:                                                                                                                                         /////
  200.             osStatus = TrackWindowProxyDrag(windowRef,eventStrucPtr->where);                                     /////
  201.             if(osStatus == errUserWantsToDragWindow)                                                                                     /////
  202.                 handled = false;                                                                                                                                 /////
  203.             else if(osStatus == noErr)                                                                                                                 /////
  204.                 handled = true;                                                                                                                                     /////
  205.  
  206.         case inDrag:                                                                                                                                                 /////
  207.             if(!handled)                                                                                                                                             /////
  208.             {                                                                                                                                                                     /////
  209.                 if(IsWindowPathSelectClick(windowRef,eventStrucPtr))                                                         /////
  210.                 {                                                                                                                                                                 /////
  211.                     if(WindowPathSelect(windowRef,NULL,&itemSelected) == noErr)                                         /////
  212.                     {                                                                                                                                                             /////
  213.                         if(LoWord(itemSelected) > 1)                                                                                                 /////
  214.                             doBringFinderToFront();                                                                                                         /////
  215.                     }                                                                                                                                                             /////
  216.                                                                                                                                                                                  /////
  217.                     handled = true;                                                                                                                                 /////
  218.                 }                                                                                                                                                                 /////
  219.             }                                                                                                                                                                     /////
  220.             if(!handled)                                                                                                                                             /////
  221.                 DragWindow(windowRef,eventStrucPtr->where,NULL);                                                                 /////
  222.             break;
  223.     }
  224. }
  225.  
  226. // ********************************************************************** doBringFinderToFront
  227.  
  228. void  doBringFinderToFront(void)                                                                                                                 /////
  229. {                                                                                                                                                                                 /////
  230.     ProcessSerialNumber    finderProcess;                                                                                                         /////
  231.                                                                                                                                                                                  /////
  232.     if(doFindProcess('MACS','FNDR',&finderProcess) == noErr)                                                             /////
  233.         SetFrontProcess(&finderProcess);                                                                                                         /////
  234.     else                                                                                                                                                                     /////
  235.         doErrorAlert(eCantFindFinderProcess);                                                                                                 /////
  236. }                                                                                                                                                                                 /////
  237.  
  238. // ***************************************************************************** doFindProcess
  239.  
  240. OSErr  doFindProcess(OSType creator,OSType type,ProcessSerialNumber *outProcSerNo)
  241. {                                                                                                                                                                                 /////
  242.     ProcessSerialNumber    procSerialNo;                                                                                                             /////
  243.     ProcessInfoRec            procInfoStruc;                                                                                                         /////
  244.     OSErr                                osError = 0;                                                                                                             /////
  245.                                                                                                                                                                                  /////
  246.     procSerialNo.highLongOfPSN = 0;                                                                                                                 /////
  247.     procSerialNo.lowLongOfPSN     = kNoProcess;                                                                                             /////
  248.                                                                                                                                                                                  /////
  249.     procInfoStruc.processInfoLength    = sizeof(ProcessInfoRec);                                                             /////
  250.     procInfoStruc.processName                = NULL;                                                                                                 /////
  251.     procInfoStruc.processAppSpec        = NULL;                                                                                                 /////
  252.     procInfoStruc.processLocation        = NULL;                                                                                                 /////
  253.                                                                                                                                                                                  /////
  254.     while(true)                                                                                                                                                         /////
  255.     {                                                                                                                                                                             /////
  256.         osError = GetNextProcess(&procSerialNo);                                                                                         /////
  257.         if(osError != noErr)                                                                                                                                 /////
  258.             break;                                                                                                                                                         /////
  259.                                                                                                                                                                                  /////
  260.         osError = GetProcessInformation(&procSerialNo,&procInfoStruc);                                             /////
  261.         if(osError != noErr)                                                                                                                                 /////
  262.             break;                                                                                                                                                         /////
  263.         if((procInfoStruc.processSignature == creator) && (procInfoStruc.processType == type)) ///
  264.             break;                                                                                                                                                         /////
  265.     }                                                                                                                                                                             /////
  266.                                                                                                                                                                                  /////
  267.     *outProcSerNo = procSerialNo;                                                                                                                     /////
  268.                                                                                                                                                                                  /////    
  269.     return osError;                                                                                                                                                 /////
  270. }                                                                                                                                                                                 /////
  271.  
  272. // ********************************************************************************** doUpdate
  273.  
  274. void  doUpdate(EventRecord *eventStrucPtr)
  275. {
  276.     WindowRef                        windowRef;
  277.     docStructureHandle    docStrucHdl;
  278.     GrafPtr                            oldPort;
  279.     Rect                                destRect;
  280.  
  281.     windowRef = (WindowRef) eventStrucPtr->message;
  282.     docStrucHdl = (docStructureHandle) GetWRefCon(windowRef);
  283.  
  284.     GetPort(&oldPort);
  285.     SetPortWindowPort(windowRef);
  286.  
  287.     BeginUpdate(windowRef);
  288.  
  289.     if((*docStrucHdl)->pictureHdl)
  290.     {
  291.         destRect = (*(*docStrucHdl)->pictureHdl)->picFrame;
  292.         OffsetRect(&destRect,170,54);
  293.         HLock((Handle) (*docStrucHdl)->pictureHdl);
  294.         DrawPicture((*docStrucHdl)->pictureHdl,&destRect);
  295.         HUnlock((Handle) (*docStrucHdl)->pictureHdl);
  296.     }
  297.     else if((*docStrucHdl)->editStrucHdl)
  298.     {
  299.         HLock((Handle) (*docStrucHdl)->editStrucHdl);
  300.         TEUpdate(&gDestRect,(*docStrucHdl)->editStrucHdl);
  301.         HUnlock((Handle) (*docStrucHdl)->editStrucHdl);
  302.     }
  303.  
  304.     if((*docStrucHdl)->windowTouched)
  305.     {
  306.         TextSize(48);
  307.         MoveTo(30,170);
  308.         DrawString("\pWINDOW TOUCHED");
  309.         TextSize(12);
  310.     }
  311.  
  312.     EndUpdate((WindowRef) eventStrucPtr->message);
  313.  
  314.     SetPort(oldPort);
  315. }
  316.  
  317. // ****************************************************************************** doMenuChoice
  318.  
  319. void  doMenuChoice(SInt32 menuChoice)
  320. {
  321.     MenuID                menuID;
  322.     MenuItemIndex    menuItem;
  323.     OSErr                    osError;
  324.     MenuCommand        commandID;
  325.  
  326.     menuID = HiWord(menuChoice);
  327.     menuItem = LoWord(menuChoice);
  328.  
  329.     if(menuID == 0)
  330.         return;
  331.  
  332.     if(menuID == mAppleApplication)
  333.     {
  334.         if(menuItem == iAbout)
  335.             SysBeep(10);
  336.     }
  337.     else
  338.     {
  339.         osError = GetMenuItemCommandID(GetMenuRef(menuID),menuItem,&commandID);
  340.         if(osError == noErr && commandID != 0)
  341.             doCommand(commandID);
  342.     }
  343.  
  344.     HiliteMenu(0);
  345. }
  346.  
  347. // ********************************************************************************* doCommand
  348.  
  349. void  doCommand(MenuCommand commandID)
  350. {
  351.     OSErr    osError;
  352.  
  353.     switch(commandID)
  354.     {
  355.         // …………………………………………………………………………………………………………………………………………………………………………………………………………… File menu
  356.  
  357.         case File_New:
  358.             if(osError = doNewCommand())
  359.                 doErrorAlert(osError);
  360.             break;
  361.  
  362.         case File_Open:
  363.             if(osError = doOpenCommand())
  364.                 doErrorAlert(osError);
  365.             break;
  366.  
  367.         case File_Close:
  368.             if(osError = doCloseCommand(kNavSaveChangesClosingDocument))
  369.                 doErrorAlert(osError);
  370.             break;
  371.  
  372.         case File_Save:
  373.             if(osError = doSaveCommand())
  374.                 doErrorAlert(osError);
  375.             break;
  376.  
  377.         case File_SaveAs:
  378.             if(osError = doSaveAsCommand())
  379.                 doErrorAlert(osError);
  380.             break;
  381.  
  382.         case File_Revert:
  383.             if(osError = doRevertCommand())
  384.                 doErrorAlert(osError);
  385.             break;
  386.  
  387.         case File_Quit:
  388.             gQuittingApplication = true;
  389.             doCloseCommand(kNavSaveChangesQuittingApplication);
  390.             break;
  391.  
  392.         // …………………………………………………………………………………………………………………………………………………………………………………… Demonstration menu
  393.  
  394.         case Demo_TouchWindow:
  395.             doTouchWindow();
  396.             break;
  397.             
  398.         case Demo_ChooseAFolderDialog:
  399.             if(osError = doChooseAFolderDialog())
  400.                 doErrorAlert(osError);
  401.             break;
  402.     }
  403. }
  404.  
  405. // ***************************************************************************** doAdjustMenus
  406.  
  407. void  doAdjustMenus(void)
  408. {
  409.     OSErr                                osError;
  410.     MenuRef                            menuRef;
  411.     WindowRef                        windowRef;
  412.     docStructureHandle    docStrucHdl;
  413.  
  414.     if(gCurrentNumberOfWindows > 0)
  415.     {
  416.         if(gRunningOnX)
  417.         {    
  418.             if((osError = GetSheetWindowParent(FrontWindow(),&windowRef)) == noErr)
  419.             {
  420.                 menuRef = GetMenuRef(mFile);
  421.                 DisableMenuCommand(menuRef,File_Close);
  422.                 DisableMenuCommand(menuRef,File_Save);
  423.                 DisableMenuCommand(menuRef,File_SaveAs);
  424.                 DisableMenuCommand(menuRef,File_Revert);
  425.                 menuRef = GetMenuRef(mDemonstration);
  426.                 DisableMenuCommand(menuRef,Demo_TouchWindow);
  427.                 return;
  428.             }
  429.             else
  430.                 windowRef = FrontWindow();
  431.         }
  432.         else
  433.             windowRef = FrontWindow();
  434.  
  435.         if(GetWindowKind(windowRef) == kApplicationWindowKind)
  436.         {
  437.             docStrucHdl = (docStructureHandle) GetWRefCon(windowRef);
  438.  
  439.             menuRef = GetMenuRef(mFile);
  440.             EnableMenuCommand(menuRef,File_Close);
  441.             if((*docStrucHdl)->windowTouched)
  442.             {
  443.                 EnableMenuCommand(menuRef,File_Save);
  444.                 EnableMenuCommand(menuRef,File_Revert);
  445.             }
  446.             else
  447.             {
  448.                 DisableMenuCommand(menuRef,File_Save);
  449.                 DisableMenuCommand(menuRef,File_Revert);
  450.             }
  451.  
  452.             if(((*docStrucHdl)->pictureHdl != NULL) || 
  453.                  ((*(*docStrucHdl)->editStrucHdl)->teLength > 0))
  454.                 EnableMenuCommand(menuRef,File_SaveAs);
  455.             else
  456.                 DisableMenuCommand(menuRef,File_SaveAs);
  457.  
  458.             menuRef = GetMenuRef(mDemonstration);
  459.  
  460.             if(((*docStrucHdl)->pictureHdl != NULL) || 
  461.                  ((*(*docStrucHdl)->editStrucHdl)->teLength > 0))
  462.             {
  463.                 if((*docStrucHdl)->windowTouched == false)
  464.                     EnableMenuCommand(menuRef,Demo_TouchWindow);
  465.                 else
  466.                     DisableMenuCommand(menuRef,Demo_TouchWindow);
  467.             }
  468.             else
  469.                 DisableMenuCommand(menuRef,Demo_TouchWindow);
  470.         }
  471.     }
  472.     else
  473.     {
  474.         menuRef = GetMenuRef(mFile);
  475.         DisableMenuCommand(menuRef,File_Close);
  476.         DisableMenuCommand(menuRef,File_Save);
  477.         DisableMenuCommand(menuRef,File_SaveAs);
  478.         DisableMenuCommand(menuRef,File_Revert);
  479.         menuRef = GetMenuRef(mDemonstration);
  480.         DisableMenuCommand(menuRef,Demo_TouchWindow);
  481.     }
  482.  
  483.     DrawMenuBar();
  484. }
  485.     
  486. // ****************************************************************************** doErrorAlert
  487.  
  488. void  doErrorAlert(SInt16 errorCode)
  489. {
  490.     Str255    errorString, theString;
  491.     SInt16    itemHit;
  492.  
  493.     if(errorCode == eInstallHandler)
  494.         GetIndString(errorString,rErrorStrings,1);
  495.     else if(errorCode == eMaxWindows)
  496.         GetIndString(errorString,rErrorStrings,2);
  497.     else if(errorCode == eCantFindFinderProcess)
  498.         GetIndString(errorString,rErrorStrings,3);
  499.     else if(errorCode == opWrErr)
  500.         GetIndString(errorString,rErrorStrings,4);
  501.     else
  502.     {
  503.         GetIndString(errorString,rErrorStrings,5);
  504.         NumToString((SInt32) errorCode,theString);
  505.         doConcatPStrings(errorString,theString);
  506.     }
  507.  
  508.     if(errorCode != memFullErr)
  509.     {
  510.         StandardAlert(kAlertCautionAlert,errorString,NULL,NULL,&itemHit);
  511.     }
  512.     else
  513.     {
  514.         StandardAlert(kAlertStopAlert,errorString,NULL,NULL,&itemHit);
  515.         ExitToShell();
  516.     }
  517. }
  518.  
  519. // ***************************************************************************** doCopyPString
  520.  
  521. void  doCopyPString(Str255 sourceString,Str255 destinationString)
  522. {
  523.     SInt16    stringLength;
  524.  
  525.     stringLength = sourceString[0];
  526.     BlockMove(sourceString + 1,destinationString + 1,stringLength);
  527.     destinationString[0] = stringLength;
  528. }
  529.  
  530. // ************************************************************************** doConcatPStrings
  531.  
  532. void  doConcatPStrings(Str255 targetString,Str255 appendString)
  533. {
  534.     SInt16    appendLength;
  535.  
  536.     appendLength = MIN(appendString[0],255 - targetString[0]);
  537.  
  538.     if(appendLength > 0)
  539.     {
  540.         BlockMoveData(appendString+1,targetString+targetString[0]+1,(SInt32) appendLength);
  541.         targetString[0] += appendLength;
  542.     }
  543. }
  544.  
  545. // ***************************************************************************** doTouchWindow
  546.  
  547. void    doTouchWindow(void)
  548. {
  549.     WindowRef                        windowRef;
  550.     docStructureHandle    docStrucHdl;
  551.  
  552.     windowRef = FrontWindow();
  553.     docStrucHdl = (docStructureHandle) GetWRefCon(windowRef);
  554.  
  555.     SetPortWindowPort(windowRef);
  556.     
  557.     TextSize(48);
  558.     MoveTo(30,170);
  559.     DrawString("\pWINDOW TOUCHED");
  560.     TextSize(12);
  561.  
  562.     (*docStrucHdl)->windowTouched = true;
  563.  
  564.     SetWindowModified(windowRef,true);                                                                                                         /////
  565. }
  566.  
  567. // *********************************************************************** openAppEventHandler
  568.  
  569. OSErr  openAppEventHandler(AppleEvent *appEvent,AppleEvent *reply,SInt32 handlerRefCon)
  570. {
  571.     OSErr    osError;
  572.  
  573.     osError = doHasGotRequiredParams(appEvent);
  574.     if(osError == noErr)
  575.         osError = doNewCommand();
  576.  
  577.     return osError;
  578. }
  579.  
  580. // ********************************************************************* reopenAppEventHandler
  581.  
  582. OSErr  reopenAppEventHandler(AppleEvent *appEvent,AppleEvent *reply,
  583.                                                              SInt32 handlerRefCon)
  584. {
  585.     OSErr    osError;
  586.  
  587.     osError = doHasGotRequiredParams(appEvent);
  588.     if(osError == noErr)
  589.         if(!FrontWindow())
  590.             osError = doNewCommand();
  591.  
  592.     return osError;
  593. }
  594.  
  595. // ************************************************************** openAndPrintDocsEventHandler
  596.  
  597. OSErr  openAndPrintDocsEventHandler(AppleEvent *appEvent,AppleEvent *reply,
  598.                                                                         SInt32 handlerRefcon)
  599. {
  600.     FSSpec            fileSpec;
  601.     AEDescList    docList;
  602.     OSErr                osError, ignoreErr;
  603.     SInt32            index, numberOfItems;
  604.     Size                actualSize;
  605.     AEKeyword        keyWord;
  606.     DescType        returnedType;
  607.     FInfo                fileInfo;
  608.  
  609.     osError = AEGetParamDesc(appEvent,keyDirectObject,typeAEList,&docList);
  610.  
  611.     if(osError == noErr)
  612.     {
  613.         osError = doHasGotRequiredParams(appEvent);
  614.         if(osError == noErr)
  615.         {
  616.             osError = AECountItems(&docList,&numberOfItems);
  617.             if(osError == noErr)
  618.             {
  619.                 for(index=1;index<=numberOfItems;index++)
  620.                 {
  621.                     osError = AEGetNthPtr(&docList,index,typeFSS,&keyWord,&returnedType,
  622.                                                                 &fileSpec,sizeof(fileSpec),&actualSize);
  623.                     if(osError == noErr)
  624.                     {
  625.                         osError = FSpGetFInfo(&fileSpec,&fileInfo);
  626.                         if(osError == noErr)
  627.                         {
  628.                             if(osError = doOpenFile(fileSpec,fileInfo.fdType))
  629.                                 doErrorAlert(osError);
  630.  
  631.                             if(osError == noErr && handlerRefcon == kPrint)
  632.                             {
  633.                                 // Call printing function here
  634.                             }
  635.                         }
  636.                     }
  637.                     else
  638.                         doErrorAlert(osError);
  639.                 }
  640.             }
  641.         }
  642.         else
  643.             doErrorAlert(osError);
  644.  
  645.         ignoreErr = AEDisposeDesc(&docList);
  646.     }
  647.     else
  648.         doErrorAlert(osError);
  649.  
  650.     return osError;
  651. }
  652.  
  653. // *********************************************************************** quitAppEventHandler
  654.  
  655. OSErr  quitAppEventHandler(AppleEvent *appEvent,AppleEvent *reply,SInt32 handlerRefcon)
  656. {
  657.     OSErr                                osError;
  658.     WindowRef                        windowRef, previousWindowRef;
  659.     docStructureHandle    docStrucHdl;
  660.     SInt16                            touchedWindowsCount = 0;
  661.     SInt16                            itemHit;
  662.  
  663.     osError = doHasGotRequiredParams(appEvent);
  664.     if(osError == noErr)
  665.     {
  666.         if(!gRunningOnX)
  667.         {
  668.             gQuittingApplication = true;
  669.             doCloseCommand(kNavSaveChangesQuittingApplication);
  670.         }
  671.         else
  672.         {
  673.             // ……………… if any window has a sheet, bring to front, play system alert sound, and return
  674.  
  675.             windowRef = GetFrontWindowOfClass(kSheetWindowClass,true);
  676.             if(windowRef)
  677.             {
  678.                 SelectWindow(windowRef);
  679.                 SysBeep(10);
  680.                 return noErr;
  681.             }
  682.  
  683.             // ……………………………………………………………………………………………………………………………………………………………………… count touched windows
  684.  
  685.             windowRef = FrontWindow();
  686.             do
  687.             {
  688.                 docStrucHdl = (docStructureHandle) GetWRefCon(windowRef);
  689.                 if((*docStrucHdl)->windowTouched == true)
  690.                     touchedWindowsCount++;
  691.                 previousWindowRef = windowRef;
  692.             } while(windowRef = GetNextWindowOfClass(previousWindowRef,kDocumentWindowClass,true));
  693.  
  694.             // …………………………………………………………………………………………………………………… if no touched windows, simply close down
  695.  
  696.             if(touchedWindowsCount == 0)
  697.                 gDone = true;
  698.  
  699.             // ………… if one touched window, cause Save Changes alert on that window, close all others
  700.  
  701.             if(touchedWindowsCount == 1)
  702.                 gQuittingApplication = true;
  703.  
  704.             // …… if more than one touched window, create Review Unsaved alert, handle button clicks
  705.  
  706.             else if(touchedWindowsCount > 1)
  707.             {
  708.                 itemHit = doReviewChangesAlert(touchedWindowsCount);
  709.  
  710.                 if(itemHit == kAlertStdAlertOKButton)
  711.                     gQuittingApplication = true;
  712.                 else if(itemHit == kAlertStdAlertCancelButton)
  713.                     gQuittingApplication = false;
  714.                 else if(itemHit == kAlertStdAlertOtherButton)
  715.                     gDone = true;
  716.             }
  717.         }    
  718.     }    
  719.  
  720.     return noErr;
  721. }
  722.  
  723. // ******************************************************************** doHasGotRequiredParams
  724.  
  725. OSErr  doHasGotRequiredParams(AppleEvent *appEvent)
  726. {
  727.     DescType    returnedType;
  728.     Size            actualSize;
  729.     OSErr            osError;
  730.  
  731.     osError = AEGetAttributePtr(appEvent,keyMissedKeywordAttr,typeWildCard,&returnedType,
  732.                                                         NULL,0,&actualSize);
  733.     if(osError == errAEDescNotFound)
  734.         osError = noErr;
  735.     else if(osError == noErr)
  736.         osError = errAEParamMissed;
  737.  
  738.     return osError;
  739. }
  740.  
  741. // ********************************************************************** doReviewChangesAlert
  742.  
  743. SInt16  doReviewChangesAlert(SInt16 touchedWindowsCount)
  744. {
  745.     AlertStdCFStringAlertParamRec    paramRec;
  746.     Str255            messageText1 = "\pYou have ";
  747.     Str255            messageText2 = "\p Files documents with unsaved changes. ";
  748.     Str255            messageText3 = "\pDo you want to review these changes before quitting?";
  749.     Str255            countString;
  750.     CFStringRef    messageText;
  751.     CFStringRef    informativeText = 
  752.                             CFSTR("If you don't review your documents, all your changes will be lost.");
  753.     DialogRef                dialogRef;
  754.     DialogItemIndex    itemHit;
  755.  
  756.     NumToString(touchedWindowsCount,countString);
  757.     doConcatPStrings(messageText1,countString);    
  758.     doConcatPStrings(messageText1,messageText2);    
  759.     doConcatPStrings(messageText1,messageText3);    
  760.   messageText = CFStringCreateWithPascalString(NULL,messageText1,CFStringGetSystemEncoding());
  761.  
  762.     GetStandardAlertDefaultParams(¶mRec,kStdCFStringAlertVersionOne);
  763.     paramRec.movable            = true;
  764.     paramRec.defaultText    = CFSTR("Review Changes…");
  765.     paramRec.cancelText        = CFSTR("Cancel");
  766.     paramRec.otherText        = CFSTR("Discard Changes");
  767.  
  768.     CreateStandardAlert(kAlertStopAlert,messageText,informativeText,¶mRec,&dialogRef);
  769.     RunStandardAlert(dialogRef,NULL,&itemHit);
  770.  
  771.     if(messageText != NULL)
  772.         CFRelease(messageText);
  773.  
  774.     return itemHit;
  775. }
  776.  
  777. // *******************************************************************************************
  778.